/*
 *  Project:            timelyRV_v0.1 -- a RISCV-32I SoC.
 *  Module name:        Interrupt_Ctrl.
 *  Description:        This module is used to contorl irqs from pkt 
 *                        sram, can, uart.
 *  Last updated date:  2022.04.03.
 *
 *  Copyright (C) 2021-2022 Junnan Li <lijunnan@nudt.edu.cn>.
 *  Copyright and related rights are licensed under the MIT license.
 *
 *  Noted:
 *    1) irq for cv32e40p: {irq_fast(Peri), 4'b0, irq_external, 3'b0,  
 *                            irq_timer, 3'b0, irq_software, 3'b0};
 */
//======================= internal reg/wire/param declarations =//
module Interrupt_Ctrl(
  //* clk & rst_n;
  input  wire                     i_clk,
  input  wire                     i_rst_n,
  //* irq (bitmap);
  input  wire [`NUM_PERI:0]       i_irq,    //* include irq_timer;
  output reg  [31:0]              o_irq,
  //* irq_ack;
  input  wire                     i_irq_ack,
  input  wire [4:0]               i_irq_id
);
  
  //======================= internal reg/wire/param declarations =//
  //* TODO, irq ctrl is simple, just one stage;
  reg         [`NUM_PERI:0]       irq_pre;
  //==============================================================//

  //======================= interrupt ctrl =======================//
  //* Commented by LCL7.
  // integer i;
  always @(posedge i_clk or negedge i_rst_n) begin
    if (!i_rst_n) begin
      o_irq                 <= 32'b0;
      irq_pre               <= {(`NUM_PERI+1){1'b0}};
    end
    else begin
      o_irq                 <= o_irq;
      irq_pre               <= i_irq;
      //* Commented by LCL7.
      // for(i=0; i<`NUM_PERI; i=i+1) begin
      //   //* set irq with '1';
      //   if(irq_pre[i] == 1'b0 && i_irq[i] == 1'b1)
      //     o_irq[16+i]       <= 1'b1;
      //   //* set irq with '0';
      //   else if(i_irq_ack == 1'b1 && i_irq_id == (i+16))
      //     o_irq[16+i]       <= 1'b0;
      //   //* maintain irq;
      //   else
      //     o_irq[16+i]       <= o_irq[16+i];
      // end

      //* UART IRQ. Inserted by LCL7.
      //* set irq with '1';
      if(irq_pre[0] == 1'b0 && i_irq[0] == 1'b1)
          o_irq[16]         <= 1'b1;
      //* set irq with '0';  
      else if(i_irq_ack == 1'b1 && i_irq_id == (16))
          o_irq[16]         <= 1'b0;
      //* maintain irq;
      else
          o_irq[16]         <= o_irq[16];
      
      //* CSR IRQ. Inserted by LCL7.
      //* set irq with '1';
      if(irq_pre[1] == 1'b0 && i_irq[1] == 1'b1)
          o_irq[19]         <= 1'b1;
      //* set irq with '0';  
      else if(i_irq_ack == 1'b1 && i_irq_id == (19))
          o_irq[19]         <= 1'b0;
      //* maintain irq;
      else
          o_irq[19]         <= o_irq[19];
      
      //* CAN IRQ. Inserted by LCL7.
      //* set irq with '1';
      if(irq_pre[2] == 1'b0 && i_irq[2] == 1'b1)
          o_irq[24]         <= 1'b1;
      //* set irq with '0';  
      else if(i_irq_ack == 1'b1 && i_irq_id == (24))
          o_irq[24]         <= 1'b0;
      //* maintain irq;
      else
          o_irq[24]         <= o_irq[24];
      
      //* DMA IRQ. Inserted by LCL7.
      //* set irq with '1';
      if(irq_pre[3] == 1'b0 && i_irq[3] == 1'b1)
          o_irq[22]         <= 1'b1;
      //* set irq with '0';  
      else if(i_irq_ack == 1'b1 && i_irq_id == (22))
          o_irq[22]         <= 1'b0;
      //* maintain irq;
      else
          o_irq[22]         <= o_irq[22];

      
      //* for irq_timer;
      if(irq_pre[`NUM_PERI] == 1'b0 && i_irq[`NUM_PERI] == 1'b1)
          o_irq[7]          <= 1'b1;
        //* set irq with '0';
        else if(i_irq_ack == 1'b1 && i_irq_id == 5'd7)
          o_irq[7]          <= 1'b0;
        //* maintain irq;
        else
          o_irq[7]          <= o_irq[7];
    end
  end
  //==============================================================//

endmodule    
